package com.ltmonitor.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;

import com.ltmonitor.entity.*;

import org.apache.activemq.command.ActiveMQObjectMessage;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

import com.ltmonitor.service.IAlarmConfigService;
import com.ltmonitor.service.IBasicDataService;
import com.ltmonitor.service.IJT809CommandService;
import com.ltmonitor.service.IPlatformStateService;
import com.ltmonitor.service.IQueryService;
import com.ltmonitor.service.ITerminalCommandService;
import com.ltmonitor.service.JT808Constants;
import com.ltmonitor.util.Constants;
import com.ltmonitor.util.DateUtil;
import com.ltmonitor.util.StringUtil;
import com.ltmonitor.util.T809Constants;
import com.ltmonitor.vo.AlarmMessage;
import com.ltmonitor.web.controller.websocket.AlarmWebSocketHandler;
import com.sun.tools.classfile.Annotation.element_value;

@Service("alarmPushService")
public class AlarmPushService implements IAlarmPushService {

	@Resource
	AlarmWebSocketHandler alarmWebSocketHandler;
	@Autowired
	protected IVehicleDataService vehicleDataService;

	@Autowired
	protected IBasicDataService basicDataService;

	/**
	 * 终端命令服务
	 */
	@Autowired
	protected ITerminalCommandService terminalCommandService;

	@Autowired
	protected IJT809CommandService jt809CommandService;

	@Autowired
	protected IPlatformStateService platformStateService;

	@Autowired
	protected IAlarmConfigService alarmConfigService;
	@Autowired
	protected IQueryService queryService;

	private static Logger logger = Logger.getLogger(AlarmPushService.class);
	private boolean startUpdate = true;
	/**
	 * 开辟线程，扫描报警记录表，获取最新的报警
	 */
	private Thread processAlarmThread;

	Map<String, Date> alarmMap = new HashMap<String, Date>();

	List<AlarmMessage> alarmMesageList = new ArrayList<AlarmMessage>();

	private ConcurrentLinkedQueue<AlarmMessage> dataQueue = new ConcurrentLinkedQueue();
	/**
	 * 通过spring配置，开机自动启动调用此方法，创建线程，在线程中不断的扫描库表
	 */
	@Override
	public void start() {
		processAlarmThread = new Thread(new Runnable() {
			public void run() {
				ProcessAlarmThreadFunc();
			}
		});
		processAlarmThread.start();

	}

	@Override
	public void pushAlarm(AlarmMessage am)
	{
		dataQueue.add(am);
	}

	private void ProcessAlarmThreadFunc() {
		while (startUpdate) {
			try {
				AlarmMessage am = null;
				this.alarmMesageList.clear();;
				while ((am = dataQueue.poll()) != null) {
					if(am.getDepId() == 0)
					{
						VehicleData vd = this.vehicleDataService.load(am.getVehicleId());
						if(vd != null)
						{
							am.setDepId(vd.getDepId());
						}
					}
					AlarmConfig ac = this.alarmConfigService.getAlarmConfig(0, am.getAlarmType(), am.getAlarmSource());
					if ( AlarmMessage.ALARM_MESSAGE.equals(am.getMessageType()) && ac != null && ac.isEnabled()) {
						// 报警声音的开关配置在meta属性中.
						am.setSoundEnabled(ac.isSoundEnabled());
						am.setPopupEnabled(ac.isPopupEnabled());

						String alarmTypeDescr = ac.getName();
						if(AlarmRecord.ALARM_FROM_TERM.equals(am.getAlarmSource())) {
							if (AlarmRecord.TYPE_IN_AREA.equals(ac.getAlarmType())
									|| AlarmRecord.TYPE_CROSS_BORDER.equals(ac.getAlarmType())
									|| AlarmRecord.TYPE_ON_ROUTE.equals(ac.getAlarmType())
									|| AlarmRecord.TYPE_OFFSET_ROUTE.equals(ac.getAlarmType())
									|| AlarmRecord.TYPE_OVER_SPEED_ON_ROUTE.equals(ac.getAlarmType())
									|| AlarmRecord.TYPE_LEAVE_NOT_ON_TIME.equals(ac.getAlarmType())
									|| AlarmRecord.TYPE_ARRIVE_NOT_ON_TIME.equals(ac.getAlarmType())) {
								alarmTypeDescr += "," + am.getLocation();
							} else if (AlarmRecord.TYPE_OVER_SPEED.equals(ac.getAlarmType())) {
								alarmTypeDescr += ",速度:" + am.getSpeed() + "km/h";
							} else if (AlarmRecord.TYPE_TIRED.equals(ac.getAlarmType())) {
								alarmTypeDescr += "," + am.getAlarmDescr();
							}
						}else if(AlarmRecord.ALARM_FROM_VIDEO.equals(am.getAlarmSource())) {

							if(StringUtil.isNullOrEmpty(am.getAlarmDescr()) == false)
							   alarmTypeDescr += "," + am.getAlarmDescr() ;
						}else if(AlarmRecord.TYPE_DISK_FULL.equals(am.getAlarmType())) {
							if(StringUtil.isNullOrEmpty(am.getAlarmDescr()) == false)
								alarmTypeDescr += "," + am.getAlarmDescr() ;
						}
						am.setAlarmDescr(alarmTypeDescr);
						if(StringUtil.isNullOrEmpty(ac.getVideoMonitorChannels()) == false )
						{
							VehicleData vd = this.vehicleDataService.load(am.getVehicleId());
							if(vd != null && vd.getVideoChannelNum() > 0)
							{
								am.setVideoChannels(ac.getVideoMonitorChannels());
							}
						}
					}else
						am.setPopupEnabled(true);//非报警消息，只弹窗
					alarmMesageList.add(am);

				}
				//alarm();

				PlatformState ps = this.platformStateService.getPlatformState();
				setPlateformStateMessage(ps); // 平台服务器状态

				if (this.alarmMesageList.size() > 0) {
					// logger.error("count:"+ jt808MesageList.size());
					alarmWebSocketHandler.broadcast(alarmMesageList);
				}
			}catch (Exception ex)
			{
				logger.error(ex.getMessage(), ex);
			}
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e1) {
				logger.error(e1.getMessage(), e1);
			}
		}
	}

	public void alarm() {
		try {

			//jt808MesageList.clear();
			//Map<String, Object> alarmData = new HashMap<String, Object>();
			/**
			String queryId = "alarm.selectLatestAlarms";
			Map<String, Object> params = new HashMap<String, Object>();
			String tableName = Constants.getAlarmTableName();
			params.put("tableName", tableName);// 报警数据是一个月一张表
			Date date = DateUtil.getDate(new Date(), Calendar.MINUTE, -2); // 当前2分钟内产生的报警
			params.put("startTime", date);
			// params.put("status", "New");
			try {
				List result = queryService.query(queryId, params);
				result = filterAlarmResult(result);
				alarmData.put("alarm", result);
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
			 */

			// 上级平台下发的808指令
			List jt808Commands = getJT808Command();
			//if (jt808Commands.size() > 0)
				//alarmData.put("jt808Notify", jt808Commands);

			// 上级平台下发的809指令
			List jt809Commands = getJT809Command();
			//if (jt809Commands.size() > 0)
				//alarmData.put("jt809Notify", jt809Commands);

			// 上级平台下发的报警督办
			List warnMsgTodoRegList = getWarnMsgTodoReq();
			//if (warnMsgTodoRegList.size() > 0)
				//alarmData.put("warnMsgTodoReq", warnMsgTodoRegList);


			//if (this.jt808MesageList.size() > 0) {
				// logger.error("count:"+ jt808MesageList.size());
				//alarmWebSocketHandler.broadcast(jt808MesageList);
			//}

		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	private List getJT809Command() {
		Map params = new HashMap();
		Date date = DateUtil.getDate(new Date(), Calendar.MINUTE, -10); // 当前一个小时内产生的报警
		params.put("createDate", date);
		params.put("source", JT809Command.DOWN_NOTIFY); // 来自平台的下发通知
		List ls = new ArrayList();
		try {
			String queryId1 = "jt809Command.selectJT809Command";
			ls = queryService.query(queryId1, params);
			ls = filterJt809Result(ls);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		return ls;
	}

	/**
	 * 查询终端上传的命令请求
	 *
	 * @return
	 */
	private List getJT808Command() {
		Map params = new HashMap();
		Date date = DateUtil.getDate(new Date(), Calendar.MINUTE, -2); // 当前10分钟内产生的报警
		params.put("startDate", date);
		params.put("owner", TerminalCommand.FROM_TERMINAL); // 来自平台的下发通知
		// params.put("depIdList", super.getAuthorizedDepIdList());//
		// 只查询本部门的车辆的终端上报消息
		List ls = new ArrayList();
		try {
			String queryId1 = "terminalCommand.selectTerminalCommand";
			ls = queryService.query(queryId1, params);
			ls = filterJt808Result(ls);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		return ls;
	}

	/**
	 * 得到报警督办信息
	 *
	 * @return
	 */
	private List getWarnMsgTodoReq() {
		Map params = new HashMap();
		Date date = DateUtil.getDate(new Date(), Calendar.HOUR, -1); // 当前一个小时内产生的报警
		params.put("createDate", date);
		List ls = new ArrayList();
		try {
			String queryId1 = "warnMsgUrgTodoReq.selectMsgTodoReq";
			ls = queryService.query(queryId1, params);
			ls = filterMsgTodoResult(ls);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		return ls;

	}

	/**
	 * 已经报警的，将不再重复弹出
	 *
	 * @param alarmList
	 * @return
	 */
	private List<AlarmMessage> filterAlarmResult(List alarmList) {
		if (alarmMap.size() > 500) {
			alarmMap.clear();
		}

		for (Object obj : alarmList) {
			Map rowData = (Map) obj;
			Integer alarmId = (Integer) rowData.get("id");
			Integer depId = (Integer) rowData.get("depId");
			// 车辆不是用户所管辖的部门
			// if (super.isAuthorizedDep(depId) == false)
			// continue;

			String key = "_" + alarmId;
			// 只推送未推送的报警，已经推送到前台的，不再推送。
			if (alarmMap.containsKey(key) == false) {
				alarmMap.put(key, new Date());
				// 查看该类型的报警，数据库中是否配置
				String alarmType = "" + rowData.get("alarmType");
				String alarmSource = "" + rowData.get("alarmSource");
				AlarmConfig ac = this.alarmConfigService.getAlarmConfig(depId, alarmType, alarmSource);
				if (ac != null && ac.isEnabled()) {
					// 报警声音的开关配置在meta属性中.
					rowData.put("soundEnabled", (Boolean) ac.isSoundEnabled());
					rowData.put("popupEnabled", (Boolean) ac.isPopupEnabled());

					String alarmTypeDescr = ac.getName();


					AlarmMessage am = new AlarmMessage();
					am.setDepId(depId);
					am.setAlarmId(alarmId);
					am.setVehicleId((Integer) rowData.get("vehicleId"));
					am.setAlarmType(alarmType);
					am.setPlateNo((String) rowData.get("plateNo"));
					am.setAlarmDescr(alarmTypeDescr);
					am.setAlarmSource(alarmSource);
					Date d = (Date) rowData.get("alarmTime");
					am.setAlarmTime(DateUtil.toStringByFormat(d, "yyyy-MM-dd HH:mm:ss"));
					am.setMessageType(AlarmMessage.ALARM_MESSAGE);
					am.setSoundEnabled(ac.isSoundEnabled());
					am.setPopupEnabled(ac.isPopupEnabled());
					alarmMesageList.add(am);
					// rowData.put("alarmTypeDescr", alarmTypeDescr);

					// convert(rowData);
				}

			}

		}
		return alarmMesageList;
	}

	private void setPlateformStateMessage(PlatformState ps) {
		AlarmMessage am = new AlarmMessage();
		am.setAlarmId(0);
		am.setAlarmDescr(ps.getMainLinkState() + "," + ps.getSubLinkState());
		Date d = new Date();
		am.setAlarmTime(DateUtil.toStringByFormat(d, "yyyy-MM-dd HH:mm:ss"));
		am.setMessageType(AlarmMessage.JT809_PLATFROM_STATE);
		alarmMesageList.add(am);
	}

	private void convert(Map rowData) {
		// 报警来源
		this.convert(rowData, "alarmSource", "AlarmSource");
		this.convert(rowData, "plateColor", "PlateColor");
		this.convert(rowData, "processed", "ProcessType");

		Date alarmDate = (Date) rowData.get("startTime");
		rowData.put("startTime", DateUtil.toStringByFormat(alarmDate, "MM-dd HH:mm:ss"));

	}

	/**
	 * 基础数据转换，将数据表中标志字段转换为文字描述
	 *
	 * @param rowData
	 * @param field
	 * @param parentCode
	 * @return
	 */
	protected String convert(Map rowData, String field, String parentCode) {
		String fieldValue = "" + rowData.get(field);
		BasicData bd = this.basicDataService.getBasicDataByCode(fieldValue, parentCode);
		if (bd != null) {
			rowData.put(field, bd.getName());
			return bd.getName();
		}
		return "";
	}

	private List<AlarmMessage> filterJt808Result(List alarmList) {

		for (Object obj : alarmList) {
			Map rowData = (Map) obj;
			Integer alarmId = (Integer) rowData.get("cmdId");
			Long depId = 0L;
			if (rowData.get("depId") != null)
				Long.parseLong("" + rowData.get("depId"));
			// Integer vehicleId = (Integer) rowData.get("vehicleId");
			String key = "808_" + alarmId;
			if (alarmMap.containsKey(key) == false) {
				alarmMap.put(key, new Date());
				// convert(rowData);
			} else
				continue;

			Date createDate = (Date) rowData.get("createDate");
			// rowData.put("createDate", DateUtil.toStringByFormat(createDate,
			// "MM-dd HH:mm:ss"));
			Integer cmdType = (Integer) rowData.get("cmdType");
			String strCmd = Integer.toHexString(cmdType);
			if (strCmd.length() < 4)
				strCmd = "0" + strCmd;
			strCmd = "0x" + strCmd;
			String descr = JT808Constants.GetDescr(strCmd);
			String cmdData = (String) rowData.get("cmdData");

			AlarmMessage am = new AlarmMessage();
			am.setDepId(depId);
			am.setAlarmId(alarmId);
			am.setVehicleId((Integer) rowData.get("vehicleId"));
			am.setAlarmType(strCmd);
			am.setPlateNo((String) rowData.get("plateNo") + descr);
			am.setAlarmDescr(cmdData);
			// am.setAlarmSource(alarmSource);
			am.setAlarmTime(DateUtil.toStringByFormat(createDate, "yyyy-MM-dd HH:mm:ss"));
			am.setMessageType(AlarmMessage.JT808_MESSAGE);
			// am.setSoundEnabled(ac.isSoundEnabled());
			am.setPopupEnabled(true);
			alarmMesageList.add(am);
		}
		return alarmMesageList;
	}

	/**
	 * 已经报警的，将不再重复弹出
	 *
	 * @param alarmList
	 * @return
	 */
	private List<AlarmMessage> filterJt809Result(List alarmList) {

		for (Object obj : alarmList) {
			Map rowData = (Map) obj;
			Integer alarmId = (Integer) rowData.get("cmdId");
			String key = "809_" + alarmId;
			if (alarmMap.containsKey(key) == false) {
				alarmMap.put(key, new Date());
				// convert(rowData);
			} else
				continue;

			String cmdData = (String) rowData.get("cmdData");
			if (StringUtil.isNullOrEmpty(cmdData)) {
				String plateNo = "" + rowData.get("plateNo");
				if (StringUtil.isNullOrEmpty(plateNo) == false) {
					cmdData = plateNo;
				} else
					cmdData = "";
			}

			Date createDate = (Date) rowData.get("createDate");

			Integer cmdType = (Integer) rowData.get("cmd");
			Integer subType = (Integer) rowData.get("subCmd");
			subType = subType == 0 ? cmdType : subType;
			String subDescr = T809Constants.getMsgDescr(subType);

			String strCmd = "0x" + Integer.toHexString(subType);
			rowData.put("cmdType", strCmd);
			rowData.put("subType", "0x" + Integer.toHexString(subType));
			rowData.put("subDescr", subDescr);
			AlarmMessage am = new AlarmMessage();
			// am.setDepId(depId);
			am.setAlarmId(alarmId);
			// am.setVehicleId((Integer)rowData.get("vehicleId"));
			am.setAlarmType(strCmd);
			am.setPlateNo(subDescr);
			am.setAlarmDescr(cmdData);
			am.setPopupEnabled(true);
			// am.setAlarmSource(alarmSource);
			am.setAlarmTime(DateUtil.toStringByFormat(createDate, "yyyy-MM-dd HH:mm:ss"));
			am.setMessageType(AlarmMessage.JT809_MESSAGE);
			// am.setSoundEnabled(ac.isSoundEnabled());
			alarmMesageList.add(am);
		}
		return alarmMesageList;
	}

	private List<AlarmMessage> filterMsgTodoResult(List alarmList) {

		for (Object obj : alarmList) {
			Map rowData = (Map) obj;
			Integer alarmId = (Integer) rowData.get("id");
			String key = "warnMsgTodo_" + alarmId;
			if (alarmMap.containsKey(key)) {
				continue;
			} else {
				alarmMap.put(key, new Date());
			}

			String warnSrc = "" + rowData.get("warnSrc");
			String warnType = "" + rowData.get("warnType");

			String supervisionLevel = "" + rowData.get("supervisionLevel");

			supervisionLevel = "0".equals(supervisionLevel) ? "紧急" : "一般";

			rowData.put("supervisionLevel", supervisionLevel);

			BasicData bd = basicDataService.getBasicDataByCode(warnSrc, "GovAlarmSrc");
			warnSrc = bd != null ? bd.getName() : "";
			rowData.put("warnSrc", warnSrc);

			bd = basicDataService.getBasicDataByCode(warnType, "GovAlarmType");
			warnType = bd != null ? bd.getName() : "";
			rowData.put("warnType", warnType);

			String plateColor = "" + rowData.get("plateColor");
			bd = basicDataService.getBasicDataByCode(plateColor, "plateColor");
			plateColor = bd != null ? bd.getName() : "";
			rowData.put("plateColor", plateColor);

			Date warnTime = (Date) rowData.get("warnTime");

			Date supervisionEndTime = (Date) rowData.get("supervisionEndTime");
			rowData.put("supervisionEndtime", DateUtil.toStringByFormat(supervisionEndTime, "MM-dd HH:mm:ss"));
			AlarmMessage am = new AlarmMessage();
			// am.setDepId(depId);
			am.setAlarmId(alarmId);
			// am.setVehicleId((Integer)rowData.get("vehicleId"));
			am.setAlarmType("报警督办");
			am.setPlateNo((String) rowData.get("plateNo") + "报警督办");
			am.setAlarmDescr((String) rowData.get("plateNo") + "报警督办");
			// am.setAlarmSource(alarmSource);
			// Date d = (Date)rowData.get("warnTime");
			am.setAlarmTime(DateUtil.toStringByFormat(warnTime, "yyyy-MM-dd HH:mm:ss"));
			am.setMessageType(AlarmMessage.JT809_MESSAGE);
			// am.setSoundEnabled(ac.isSoundEnabled());
			alarmMesageList.add(am);
		}
		return alarmMesageList;
	}

}
